/*
 * Copyright 2010, 2011 Matt Oliveri
 *
 * This file is part of JConfigGen
 *
 * JConfigGen is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JConfigGen is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JConfigGen.  If not, see <http://www.gnu.org/licenses/>.
 */

package atma.jconfiggen;

import java.io.PrintStream;

/** Refer to the result of a {@link Proxy}.
 * <p>
 * A {@code PxRef} expression evaluates to the same result as the {@link Proxy} it refers to.
 * The {@link Proxy} (including its subexpression) is not reevaluated.
 * </p>
 * <p>
 * There is a restriction on where a {@code PxRef} can be, relative to the {@link Proxy} it refers to.
 * If this restriction is violated, the generated Java code will be rejected by the compiler.
 * The restriction is that the result of the {@link Proxy} must be in scope where the {@code PxRef} appears.
 * </p>
 * <p>
 * The "scope" of a {@link Proxy} result never includes areas where the {@link Proxy} has not yet been evaluated.
 * (So, in other words, the {@code PxRef} must appear after the {@link Proxy} in evaluation order.)
 * Also, this "scope" is at least as wide as the scope of the id if the {@link Proxy} result were assigned an id.
 * In fact, if the {@link Proxy} result <i>is</i> assigned an id, the two notions of scope coincide.
 * But usually the {@link Proxy} result will not be assigned an id, because that would kind of defeat the purpose of using a {@link Proxy}.
 * </p>
 * <p>
 * If the {@link Proxy} result is not assigned an id, the result scope can extend outside of a block that contains the {@link Proxy} if
 *   the result of the expression that introduces the block is the same as the {@link Proxy} result.
 * Let's call this quirk "block escaping".
 * The sameness of the block expression result and {@link Proxy} result that allows for block escaping is not just that at runtime, the values happen to be equal.
 * (In general there's no way to statically anticipate that.)
 * What's going on is that in the generated code, sometimes the result of an expression inside a block will be assigned to a variable declared outside the block.
 * The "scope" of the {@link Proxy} result corresponds to the area in the Java code where the variable chosen for the result is both in scope and definitely initialized.
 * The rules for how results are assigned to variables are complex, but reasonable, so if you look at the generated code, you can probably figure what's going on.
 * If you want to play it safe though, feel free to not take advantage of block escaping.
 * (The reason why block escaping never happens if the {@link Proxy} result is assigned an id is because you basically told JConfigGen to put the result in a new variable with the specified name.
 * The new variable will go in the same block as the expression assigned the id.)
 * </p>
 */
public final class PxRef extends Expr
{
	private final Proxy px;

	/** Construct a {@code PxRef}.
	 * @param p The {@link Proxy} to refer to. Cannot be null.
	 */
	public PxRef(Proxy p) {px = p;}

	void printType(PrintStream out) throws InvalidConfigException {px.printType(out);}
	boolean hasStats() {return false;}
	void discard() {}
	void statize() {}
	boolean useId(String i) {return px.useId(i);}
	void printStats(PrintStream out,int tabs) {}
	void printExpr(PrintStream out) {px.printExpr(out);}
}
